<template>
  <el-dialog
    v-if="dialogVisible"
    :title="`比赛分数${writeable ? '编辑' : '详情'}`"
    :model-value="dialogVisible"
    :close-on-click-modal="!writeable"
    class="dialog-warp"
    width="80%"
    @update:model-value="emit('update:dialogVisible', $event)"
  >
    <el-form
      ref="tableFormRef"
      :model="listData"
      :rules="rules"
      class="form-warp"
    >
      <div
        v-for="(participant, index) in listData"
        :key="index"
        v-loading="participant.loading"
        class="item-warp"
      >
        <div v-if="participant?.hasLines || index === 0">
          <div class="table-title">
            <p>{{ participant.type || '比赛成绩' }}</p>
            <div class="title-right">
              <el-button
                v-if="writeable"
                class="button-search"
                type="danger"
                plain
                @click="editHandler(participant)"
              >
                {{ participant.writeable ? '保存' : '编辑' }}
              </el-button>
            </div>
          </div>
          <table-custom
            v-loading="tableLoading"
            :table-data="participant.tableData"
            :columns="participant.columns"
            :show-operations="false"
          >
            <template
              v-for="col in participant.columns"
              v-slot:[col.prop]="{ row, rowIndex, value }"
            >
              <template v-if="col.type !== 'image'">
                <span v-if="col.type === 'time' && !participant.writeable">
                  {{
                    getTime(
                      value,
                      participant.tableData[rowIndex].useTimeMillisecond
                    )
                  }}
                </span>
                <el-form-item
                  v-else-if="isEditableField(col.prop) && participant.writeable"
                  :prop="`[${index}].tableData[${rowIndex}].${col.prop}`"
                >
                  <el-input
                    v-if="col.type === 'integer'"
                    v-model="row[col.prop]"
                    v-format.integer="{ grouping: false }"
                    size="small"
                    @change="handleIntegerChange(row, col.prop)"
                    @blur="handleIntegerBlur(row, col.prop)"
                  />
                  <el-input
                    v-else-if="col.type === 'negative'"
                    v-model="row[col.prop]"
                    v-format.integer.negative="{ grouping: false }"
                    size="small"
                    @change="handleIntegerChange(row, col.prop)"
                    @blur="handleIntegerBlur(row, col.prop)"
                  />
                  <!-- @input="handleFieldChange(row, col.prop, $event, col.type)"
                  @blur="handleFieldBlur(row, col.prop, $event, col.type)" -->
                  <el-input
                    v-else-if="col.type === 'text'"
                    v-model="row[col.prop]"
                    v-format.text
                    size="small"
                  />
                  <el-select
                    v-else-if="col.type === 'select'"
                    v-model="row[col.prop]"
                    class="m-2"
                    placeholder="请选择"
                    size="small"
                  >
                    <el-option
                      v-for="item in honorOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                  <div
                    v-else-if="col.type === 'time'"
                    class="timer-warp"
                    :class="{
                      'timer-warp-focus': row.focus,
                      'timer-warp-hover': row.hover,
                    }"
                  >
                    <el-time-picker
                      v-model="row[col.prop]"
                      :clearable="false"
                      format="HH:mm:ss"
                      default-value="0"
                      placeholder="比赛用时"
                      @focus="row.focus = true"
                      @blur="row.focus = false"
                    />
                    <el-input-number
                      v-model.number.trim.lazy="row[col.prop + 'Millisecond']"
                      class="time-millisecond"
                      v-format.integer="{ grouping: false }"
                      :min="0"
                      :max="999"
                      :controls="false"
                      @focus="row.focus = true"
                      @blur="row.focus = false"
                    ></el-input-number>
                  </div>
                  <el-input v-else v-model="row[col.prop]" size="small" />
                </el-form-item>
                <span v-else>{{ value }}</span>
              </template>
            </template>
          </table-custom>
        </div>
      </div>
    </el-form>
  </el-dialog>
</template>

<script setup>
import { defineProps, defineEmits, ref, watch, computed } from 'vue'
import tableCustom from '@/components/tableCustom.vue'
import { ElMessage, ElLoading } from 'element-plus'
import { groupEditListGenerate } from '@/utils/group'
import {
  calculateScore,
  totalPoints,
  defaultScore,
} from '@/utils/calculateScore'
import { scoreEditColumnsConfig, readOnlyFields } from '@/config/type'
import { getRules, getDuration, msToTime, getTime } from '@/config/rules'
import { typeStatus } from '@/config/type'
import {
  droneApi,
  fireApi,
  gobangApi,
  logisticsApi,
  obstacleApi,
} from '@/api/modules'

const props = defineProps({
  dialogVisible: {
    type: Boolean,
    default: false,
  },
  writeable: {
    type: Boolean,
    default: false,
  },
  row: {
    type: Object,
    default: () => {},
  },
  type: {
    type: String,
    default: '',
  },
  playType: {
    type: Number,
  },
  knockoutRound: {
    type: Number,
  },
  status: {
    type: String,
    default: '',
  },
})

const columns = computed(() => scoreEditColumnsConfig[props.type])
const rules = computed(() => getRules(props.type, listData.value))
const isLogisticsOrFire = computed(() => {
  return ['fire', 'logistics'].includes(props.type)
})

const apiHandle = {
  drone: droneApi,
  fire: fireApi,
  obstacle: obstacleApi,
  logistics: logisticsApi,
  gobang: gobangApi,
}

const listData = ref([
  { type: '小组循环赛成绩', columns, tableData: [], hasLines: false },
  { type: '抢位赛成绩', columns, tableData: [], hasLines: false },
  { type: '淘汰赛成绩', columns, tableData: [], hasLines: false },
])
const honorOptions = ref([
  { value: 1, label: '第一、四名 得1分' },
  { value: 2, label: '第一、三名 得2分' },
  { value: 3, label: '第一、二名 得3分' },
  { value: 0, label: '第二、三名 得0分' },
  { value: 0, label: '第二、四名 得0分' },
  { value: 0, label: '第三、四名 得0分' },
])

const loadingScreen = () => {
  return ElLoading.service({
    lock: true,
    text: '正在加载数据...',
    background: 'rgba(0, 0, 0, 0.7)',
  })
}
const countPoints = (array) => {
  array.forEach((item) => {
    const { date, ms } = msToTime(item.useTime)
    item.useTime = date
    item.useTimeMillisecond = ms
    item.statusText = typeStatus[item.status]
    defaultScore[props.type].forEach((prop) => {
      // 给个默认值，简化操作，后台没有0无法进行下阶段，每个字段就都成了必填项了
      item[prop.name] = item[prop.name] || 0
    })
    if (props.type === 'obstacle') {
      item.points = totalPoints(item)
    }
  })
}
const getGroupList = async () => {
  const loading = loadingScreen()
  const res = await apiHandle[props.type].goupPersonQuery.post({
    regNo: props.row.regNo,
    batchNo: props.row.batchNo,
    groupCategory: props.row.groupCategory,
    playType: props.playType,
  })
  if (res.code !== 200) {
    ElMessage.error('查询错误!')
    loading.close()
    return
  }
  const groupList = groupEditListGenerate(res.data || [], readOnlyFields)
  countPoints(groupList, props.type)
  listData.value = [
    {
      type: '小组循环赛成绩',
      columns,
      tableData: groupList,
    },
  ]
  loading.close()
}
const getTableData = async () => {
  // 清空数据
  listData.value = [
    { type: '比赛成绩', columns, hasLines: true, tableData: [] },
  ]
  if (!props.type || props.type === 'end') {
    ElMessage.error('比赛状态获取错误!')
    return
  }
  // 如果是小组赛
  if (props.status === 'group' && props.writeable) {
    getGroupList()
    return
  }
  // 如果当前阶段不是小组赛
  const loading = loadingScreen()
  const res = await apiHandle[props.type].queryPageList.post({
    pageNum: 1,
    pageSize: 10000, // 获取所有数据
    regNo: props.row.regNo,
    batchNo: props.row.batchNo,
    groupCategory: props.row.groupCategory,
    playType: props.playType,
  })
  if (res.code !== 200) {
    ElMessage.error(res.message || '查询错误!')
    loading.close()
    return
  }
  loading.close()
  let dataArray = []
  if (Array.isArray(res?.data?.list)) dataArray = res.data.list
  else if (Array.isArray(res?.data)) dataArray = res.data
  else if (res.data.id === null) dataArray = []
  else dataArray = [res.data]
  dataArray = dataArray.reverse()

  countPoints(dataArray, props.type)
  if (isLogisticsOrFire.value) {
    listData.value = [
      { type: '比赛成绩', columns, hasLines: true, tableData: dataArray },
    ]
    return
  }
  const comTypes = {
    group: 0, // 小组赛
    position: 1, // 抢位赛
    knockout: 2, // 淘汰赛
    thirdPlace: 3, // 季军赛
    final: 4, // 决赛
  }
  const result = dataArray.reduce(
    (prev, cur) => {
      const typeIndex = comTypes[cur.status]
      prev[typeIndex].tableData.push(cur)
      prev[typeIndex].hasLines = true // 是否在页面展示这一类数据
      return prev
    },
    [
      { type: '小组循环赛成绩', columns, tableData: [], writeable: false },
      { type: '抢位赛成绩', columns, tableData: [] },
      { type: '淘汰赛成绩', columns, tableData: [] },
      { type: '季军赛成绩', columns, tableData: [] },
      { type: '决赛成绩', columns, tableData: [] },
    ]
  )
  result[0].tableData = result[0].tableData
  listData.value = result
}
watch(
  () => props.dialogVisible,
  () => {
    if (props.dialogVisible) {
      console.log('props', props.type, props.playType)
      getTableData()
    }
  }
)

let hasError = false
const validateScores = (row) => {
  const errors = {}
  let hasErrMsg = false
  for (const rule of rules) {
    if (!row[rule.key] && row[rule.key] !== 0) {
      errors[rule.key] = true
      if (!hasErrMsg) hasErrMsg = true
      if (!hasError) {
        ElMessage.error(rule.message)
        hasError = true
      }
    }
  }
  row.errors = errors
  return hasErrMsg
}

const tableFormRef = ref(null)
const editHandler = async (item) => {
  if (item.writeable) {
    const valid = await tableFormRef.value.validate()
    if (!valid) return

    // 只取部分字段做更新
    let params = item.tableData.reduce((prev, cur) => {
      const newLine = { id: cur.id }
      for (const key in cur) {
        if (readOnlyFields.includes(key)) continue
        newLine[key] = cur[key]
      }
      newLine.useTime =
        getDuration(cur.useTime) + (Number(cur.useTimeMillisecond) || 0)
      prev.push(newLine)
      return prev
    }, [])
    if (props.status === 'group') {
      const fieldObject = {}
      params = params.reduce((prev, cur) => {
        for (const key in cur) {
          // 如果没有id，说明是新的行，直接添加并退出循环
          if (!(cur.id in fieldObject)) {
            fieldObject[cur.id] = cur
            prev.push(cur)
            break
          }
          // 如果有id，说明是同一个人的数据，小组赛每人只存一条数据，故将值相加
          if (['basePhoto', 'id'].includes(key)) continue
          fieldObject[cur.id][key] =
            Number(fieldObject[cur.id][key] || 0) + Number(cur[key] || 0)
        }
        return prev
      }, [])
    }

    item.loading = true
    const res = await apiHandle[props.type].scoreUpdate.post(params)
    if (res.code !== 200) {
      item.loading = false
      ElMessage.error(res.message || '保存失败!')
      return
    }
    ElMessage.success('保存成功!')
    item.writeable = false
    item.loading = false
  } else {
    item.writeable = true
  }
}

const countTotalScore = (row, prop) => {
  if (!row.changed && (prop === 'basicScore' || prop === 'bonusScore')) {
    row.totalScore = Number(row.basicScore || 0) + Number(row.bonusScore || 0)
  }
}

const emit = defineEmits(['update:dialogVisible'])

// 判断字段是否可编辑
const isEditableField = (field) => {
  return props.writeable && !readOnlyFields.includes(field)
}

const handleIntegerChange = (row, prop) => {
  if (prop === 'totalScore') {
    row.changed = true
  }
}
const handleIntegerBlur = (row, prop) => {
  if (isLogisticsOrFire.value) {
    // 如果是总分或者有手动填写有效总分，直接返回
    if (prop !== 'totalScore') {
      if (
        !row.changed ||
        row.totalScore === '' ||
        row.totalScore === null ||
        row.totalScore === undefined
      ) {
        row.totalScore = calculateScore(row, props.type)
      }
    }
  } else if (props.type === 'obstacle') {
    // 自动计算积分
    if (prop !== 'honorValue') {
      row.points = totalPoints(row)
    }
  }
}

const handleScoreChange = (row, prop, value) => {
  row[prop] = value
  if (prop === 'totalScore') {
    row.changed = true
    return
  }
}
// 处理字段值变化
const handleFieldChange = (row, prop, value, type) => {
  let newValue = value
  row[prop] = newValue
  if (isScoreField(prop)) {
    if (prop !== 'totalScore') {
      // 自动计算总分
      row.totalScore = Number(row.basicScore || 0) + Number(row.bonusScore || 0)
    }
    handleScoreChange(row, prop, value)
  }
}
const handleFieldBlur = (row, prop, value, type) => {}
</script>

<style scoped lang="scss">
.dialog-warp {
  min-width: 500px;
  max-width: 2000;
}
.form-warp {
  .el-form-item {
    margin-bottom: 0;
  }
  :deep .el-select__selection {
    height: 32px;
  }
  :deep .el-select__wrapper.is-focused {
    box-shadow: 0 0 0 1px #cfa86c inset;
  }
}
.item-warp {
  margin-bottom: 10px;
}
.table-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 5px 5px 0 0;
  background-color: #cfa86c;
  p {
    font-size: 14px;
    padding: 5px 10px;
    margin: 0;
    text-align: left;
    color: #f7f7f7;
  }
  .el-button {
    margin-right: 10px;
  }
}
:deep .el-table .el-table__body-wrapper div.cell {
  padding: 2px;
  & > span {
    display: inline-block;
    max-width: 100%;
    margin: 6px 10px 0px 10px;
    text-overflow: ellipsis;
    overflow: hidden;
  }
  input {
    line-height: 30px;
    height: 33px;
  }
  .el-input__wrapper,
  .el-select__wrapper {
    &.is-focus {
      box-shadow: 0 0 0 1px #cfa86c inset;
    }
    + .el-form-item__error {
      display: none;
    }
  }

  .el-image {
    top: 2px;
    left: 5px;
    width: 91% !important;
    height: 29px !important;
    overflow: hidden;
    transform: scale(1.1);
    vertical-align: middle;
    image {
      height: 33px;
    }
    .image-empty .el-empty__description {
      transform: none;
    }
  }
  .timer-warp {
    display: flex;
    border: 1px solid #dcdfe6;
    border-radius: 5px;
    max-width: 100%;
  }
  .timer-warp-hover {
    border-color: #c0c4cc;
    .el-date-editor .el-input__wrapper {
      border-color: #c0c4cc;
    }
  }
  .timer-warp-focus {
    border-color: #cfa86c;
    .el-date-editor .el-input__wrapper {
      border-color: #cfa86c;
    }
  }
  .is-error .timer-warp,
  .is-error .el-date-editor .el-input__wrapper,
  .is-error .timer-warp-focus {
    border-color: #ff6a00;
  }
  .el-date-editor {
    width: 70px;
    height: 33px;
    .el-input__wrapper {
      padding: 1px 4px 1px 8px;
      border-radius: 5px 0 0 5px;
      box-shadow: none;
      border-right: 1px solid #dcdfe6;
    }
    .el-input__prefix {
      width: 70px;
      display: none;
    }
  }
  .time-millisecond {
    flex: 1;
    border-radius: 0 5px 5px 0;
    .el-input__wrapper {
      padding: 0 8px 0 3px;
      box-shadow: none;
    }
  }
}
.score-input-wrapper {
  display: flex;
  align-items: center;
  gap: 8px;
  .el-input {
    width: 100px;
  }
}
</style>
